package mn.idax.exchange.otc.util;

import com.google.gson.annotations.SerializedName;
import mn.idax.exchange.otc.constant.Constant;
import org.springframework.beans.BeanUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

public class ObjectUtils {

    /**
     * 生成待签名的字符串
     * 将对象序列化为有序的Key=Value字符串，按Key排列 支持SerializedName注解，支持自定义的DontSign注解
     *
     * @param o
     * @return String
     */
    public static String objectToSortedKeyValue(Object o) {

        ArrayList<String> list = new ArrayList<String>();


        Class<? extends Object> cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();

        for (Field f : fields) {
            f.setAccessible(true);
            try {
                String k = null;

                if ((f.getModifiers() & Modifier.STATIC) != 0) {
                    continue;
                }
                if (f.isAnnotationPresent(SerializedName.class)) {
                    SerializedName a = f.getAnnotation(SerializedName.class);
                    k = a.value();
                } else {
                    k = f.getName();
                }

                if (f.get(o) != null && !Constant.EMPTY_STR.equals(f.get(o)) && !f.isAnnotationPresent(DontSign.class)) {
                    list.add(k + "=" + f.get(o));
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        int size = list.size();
        String[] arrayToSort = list.toArray(new String[size]);
        Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < size; i++) {
            sb.append(arrayToSort[i]);
            // 最后一个字段不输出 & 符号
            if (i < size - 1) {
                sb.append("&");
            }
        }

        String result = sb.toString();
        return result;
    }

    /**
     * sortMap
     * @param paramMap
     * @return
     */
    public static  String sortMap(Map<String,Object> paramMap){
        TreeMap<String,Object> treeMap =new TreeMap(paramMap);
        StringBuffer strBuffer = new StringBuffer();
        for (String key : treeMap.keySet()) {
            strBuffer.append(key).append("=").append(paramMap.get(key)).append("&");

        }
        strBuffer.deleteCharAt(strBuffer.length()-1);
        return strBuffer.toString();
    }

    /**
     * 复制集合
     * @param source
     * @param target
     * @param <E>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <E>List copyTo(List<?> source,Class<E> target)throws IllegalAccessException, InstantiationException{
        if(source.size() == 0 || source == null){
            return  Collections.emptyList();
        }
        List<E> resList = new ArrayList<>(source.size());
        for (Object o:source){
            E e=target.newInstance();
            BeanUtils.copyProperties(o,e);
            resList.add(e);
        }
        return resList;
    }

    /**
     * transBean2Map
     *
     * @param obj obj
     * @return Map
     */
    public static Map<String, Object> transBean2Map(Object obj) {

        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>(1000);
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!Constant.CLASS.equals(key)) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }
            }
        } catch (Exception e) {
            LogUtils.error(ObjectUtils.class,"transBean2Map Error :" + e);
        }
        return map;

    }
}
